// Copyright (C) Kumo inc. and its affiliates.
// Author: Jeff.li lijippy@163.com
// All rights reserved.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published
// by the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program.  If not, see <https://www.gnu.org/licenses/>.
//

#include <nebula/bits/bitmap.h>

#include <cstdint>
#include <cstring>
#include <memory>
#include <string>

#include <nebula/array/array_primitive.h>
#include <nebula/core/buffer.h>
#include <nebula/bits/bitmap_ops.h>
#include <turbo/log/logging.h>

namespace nebula::internal {

    std::string Bitmap::to_string() const {
        std::string out(length_ + ((length_ - 1) / 8), ' ');
        for (int64_t i = 0; i < length_; ++i) {
            out[i + (i / 8)] = get_bit(i) ? '1' : '0';
        }
        return out;
    }

    std::string Bitmap::Diff(const Bitmap &other) const {
        auto this_buf = std::make_shared<Buffer>(data_, length_);
        auto other_buf = std::make_shared<Buffer>(other.data_, other.length_);

        auto this_arr = std::make_shared<BooleanArray>(length_, this_buf, nullptr, 0, offset_);
        auto other_arr =
                std::make_shared<BooleanArray>(other.length_, other_buf, nullptr, 0, other.offset_);

        return this_arr->Diff(*other_arr);
    }

    void Bitmap::CopyFrom(const Bitmap &other) {
        ::nebula::internal::CopyBitmap(other.data_, other.offset_, other.length_, mutable_data_,
                                       offset_);
    }

    void Bitmap::CopyFromInverted(const Bitmap &other) {
        ::nebula::internal::InvertBitmap(other.data_, other.offset_, other.length_,
                                         mutable_data_, offset_);
    }

    bool Bitmap::equals(const Bitmap &other) const {
        if (length_ != other.length_) {
            return false;
        }
        return BitmapEquals(data_, offset_, other.data_, other.offset(), length_);
    }

    int64_t Bitmap::BitLength(const Bitmap *bitmaps, size_t N) {
        for (size_t i = 1; i < N; ++i) {
                    DKCHECK_EQ(bitmaps[i].length(), bitmaps[0].length());
        }
        return bitmaps[0].length();
    }

}  // namespace nebula::internal
